package http

import (
	"context"
	"net/http"
	"net/url"

	"open/internal/service/notify"

	http1 "github.com/go-kratos/kratos/v2/transport/http"
	"github.com/go-kratos/kratos/v2/transport/http/binding"
	"github.com/gorilla/mux"

	v1 "open/api/open/notify/v1"
)

// NotifyHandler 外部通知handler
type NotifyHandler struct {
}

// NewNotifyHandler 新建通知handle
func NewNotifyHandler(srv *notify.Service, opts ...http1.HandleOption) http.Handler {
	h := http1.DefaultHandleOptions()
	for _, o := range opts {
		o(&h)
	}
	r := mux.NewRouter()

	r.HandleFunc("/v1/notify/message/wechat/open/{component_app_id}/{notify_app_id}", func(w http.ResponseWriter, r *http.Request) {
		var in v1.NotifyWechatOpenAppRequest
		if err := h.Decode(r, &in); err != nil {
			h.Error(w, r, err)
			return
		}

		if err := binding.MapProto(&in, mux.Vars(r)); err != nil {
			h.Error(w, r, err)
			return
		}
		if err := binding.BindForm(r, &in); err != nil {
			h.Error(w, r, err)
			return
		}

		next := func(ctx context.Context, req interface{}) (interface{}, error) {
			return srv.NotifyWechatOpenApp(ctx, req.(*v1.NotifyWechatOpenAppRequest))
		}
		if h.Middleware != nil {
			next = h.Middleware(next)
		}
		out, err := next(r.Context(), &in)
		if err != nil {
			h.Error(w, r, err)
			return
		}
		_, _ = w.Write([]byte(out.(*v1.NotifyWechatOpenAppReply).Message))
	}).Methods("POST")

	r.HandleFunc("/v1/notify/authorize/wechat/open/{component_app_id}", func(w http.ResponseWriter, r *http.Request) {
		var in v1.NotifyWechatOpenAppAuthorizeRequest
		if err := h.Decode(r, &in); err != nil {
			h.Error(w, r, err)
			return
		}

		if err := binding.MapProto(&in, mux.Vars(r)); err != nil {
			h.Error(w, r, err)
			return
		}
		if err := binding.BindForm(r, &in); err != nil {
			h.Error(w, r, err)
			return
		}

		next := func(ctx context.Context, req interface{}) (interface{}, error) {
			return srv.NotifyWechatOpenAppAuthorize(ctx, req.(*v1.NotifyWechatOpenAppAuthorizeRequest))
		}
		if h.Middleware != nil {
			next = h.Middleware(next)
		}
		out, err := next(r.Context(), &in)
		if err != nil {
			h.Error(w, r, err)
			return
		}
		_, _ = w.Write([]byte(out.(*v1.NotifyWechatOpenAppAuthorizeReply).Message))
	}).Methods("POST")

	r.HandleFunc("/v1/notify/wechat/mp/{app_id}", func(w http.ResponseWriter, r *http.Request) {
		var in v1.NotifyWechatMPAppRequest
		if err := h.Decode(r, &in); err != nil {
			h.Error(w, r, err)
			return
		}

		if err := binding.MapProto(&in, mux.Vars(r)); err != nil {
			h.Error(w, r, err)
			return
		}
		if err := binding.BindForm(r, &in); err != nil {
			h.Error(w, r, err)
			return
		}

		next := func(ctx context.Context, req interface{}) (interface{}, error) {
			return srv.NotifyWechatMPApp(ctx, req.(*v1.NotifyWechatMPAppRequest))
		}
		if h.Middleware != nil {
			next = h.Middleware(next)
		}
		_, err := next(r.Context(), &in)
		if err != nil {
			h.Error(w, r, err)
			return
		}
		_, _ = w.Write([]byte("success"))
	}).Methods("POST")

	r.HandleFunc("/v1/notify/wechat/mp/{app_id}", func(w http.ResponseWriter, r *http.Request) {
		var in v1.CheckMPRequest
		if err := h.Decode(r, &in); err != nil {
			h.Error(w, r, err)
			return
		}

		if err := binding.MapProto(&in, mux.Vars(r)); err != nil {
			h.Error(w, r, err)
			return
		}
		if err := binding.BindForm(r, &in); err != nil {
			h.Error(w, r, err)
			return
		}

		next := func(ctx context.Context, req interface{}) (interface{}, error) {
			return srv.CheckMP(ctx, req.(*v1.CheckMPRequest))
		}
		if h.Middleware != nil {
			next = h.Middleware(next)
		}
		out, err := next(r.Context(), &in)
		if err != nil {
			h.Error(w, r, err)
			return
		}
		_, _ = w.Write([]byte(out.(*v1.CheckMPReply).Message))
	}).Methods("GET")

	r.HandleFunc("/v1/notify/bytedance", func(w http.ResponseWriter, r *http.Request) {
		var in v1.NotifyBytedanceRequest
		if err := h.Decode(r, &in); err != nil {
			h.Error(w, r, err)
			return
		}

		next := func(ctx context.Context, req interface{}) (interface{}, error) {
			return srv.NotifyBytedance(ctx, req.(*v1.NotifyBytedanceRequest))
		}
		if h.Middleware != nil {
			next = h.Middleware(next)
		}
		_, err := next(r.Context(), &in)
		if err != nil {
			h.Error(w, r, err)
			return
		}
		_, _ = w.Write([]byte("success"))
	}).Methods("POST")

	r.HandleFunc("/v1/notify/bytedance/{app_id}", func(w http.ResponseWriter, r *http.Request) {
		var in v1.NotifyBytedanceRequest
		if err := h.Decode(r, &in); err != nil {
			h.Error(w, r, err)
			return
		}

		next := func(ctx context.Context, req interface{}) (interface{}, error) {
			return srv.NotifyBytedance(ctx, req.(*v1.NotifyBytedanceRequest))
		}
		if h.Middleware != nil {
			next = h.Middleware(next)
		}
		_, err := next(r.Context(), &in)
		if err != nil {
			h.Error(w, r, err)
			return
		}
		_, _ = w.Write([]byte("success"))
	}).Methods("POST")

	r.HandleFunc("/v1/notify/alipay", func(w http.ResponseWriter, r *http.Request) {
		// 支付宝直接把url.Values 传递进去方便校验参数
		var in url.Values
		if err := r.ParseForm(); err != nil {
			h.Error(w, r, err)
			return
		}
		in = r.Form
		next := func(ctx context.Context, req interface{}) (interface{}, error) {
			return srv.NotifyAlipay(ctx, req.(url.Values))
		}
		if h.Middleware != nil {
			next = h.Middleware(next)
		}
		resp, err := next(r.Context(), in)
		if err != nil {
			h.Error(w, r, err)
			return
		}
		_, _ = w.Write([]byte(resp.(string)))
	}).Methods("POST")
	return r
}
